package cqrtplm.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageInfo;
import com.hustcad.plm.basic.util.TyplmEntityBaseUtil;
import com.hustcad.plm.basic.util.TyplmLoggerUtil;
import com.hustcad.plm.pdm.common.util.CommonUtil;
import com.hustcad.plm.pdm.user.mapper.TyOrgMapper;
import com.hustcad.plm.pdm.user.model.dto.OrgExtParamDTO;
import com.hustcad.plm.pdm.user.model.dto.PrincipalParamDTO;
import com.hustcad.plm.pdm.user.service.TyplmGroupService;
import com.hustcad.plm.pdm.user.service.TyplmMemberLinkService;
import com.hustcad.plm.pdm.user.service.TyplmOrgContainerService;
import com.hustcad.plm.pdm.user.service.TyplmOrgService;
import com.hustcad.plm.pdm.user.service.TyplmPrincipalService;
import com.ty.basic.entity.CTyEntityBaseDO;
import com.ty.basic.entity.IdentifierEntity;
import com.ty.basic.entity.PrincipalEntity;
import com.ty.basic.entity.org.GroupDO;
import com.ty.basic.entity.org.OrgContainerDO;
import com.ty.basic.entity.org.OrgDO;
import com.ty.basic.entity.org.UserDO;
import com.ty.basic.handler.exceptionhandler.exception.ResponseCodeEnum;
import com.ty.basic.handler.exceptionhandler.exception.TyException;
import com.ty.basic.util.EntityBaseUtil;
import cqrtplm.constant.RTErrorCodeEnum;
import cqrtplm.service.RTOrgService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigInteger;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

@Service
@Slf4j
public class RTOrgServiceImpl implements RTOrgService {

    @Resource
    private TyplmOrgService typlmOrgService;
    @Resource
    private TyplmOrgContainerService typlmOrgContainerService;
    @Resource
    private TyOrgMapper tyOrgMapper;
    @Resource
    private TyplmMemberLinkService typlmMemberLinkService;
    @Resource
    private TyplmPrincipalService typlmPrincipalService;

    @Resource
    private TyplmGroupService typlmGroupService;
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public void createDepartment(OrgExtParamDTO paramDTO, BigInteger oid) {
        OrgDO parentOrg = this.typlmOrgService.queryOrgById(paramDTO.getParentOid());
        if (parentOrg == null) {
            throw new TyException(Collections.singletonList(new TyException(ResponseCodeEnum.BIZ_OBJECT_NOT_FOUND, new String[]{TyplmEntityBaseUtil.getTypeDisplayToIdsString("ty.inteplm.org.CTyOrg", Collections.singletonList(paramDTO.getParentOid()))})));
        } else {
            OrgContainerDO orgContainer = this.typlmOrgContainerService.queryOrgContainerByOrg(parentOrg);
            if (orgContainer == null) {
                throw new TyException(Collections.singletonList(new TyException(ResponseCodeEnum.BIZ_OBJECT_NOT_FOUND, new String[]{"orgContainer"})));
            } else {
                OrgDO orgDO = bulidNewOrgDO(paramDTO.getName(), oid, paramDTO.getDescription(), orgContainer, new IdentifierEntity(orgContainer.getDomainoid(), orgContainer.getDomainotype()));
                if (this.checkExistName(paramDTO)) {
                    return;
                }

                this.tyOrgMapper.insertSelective(orgDO);
                this.typlmMemberLinkService.insertMemberLinkByAB(paramDTO.getParentOid(), paramDTO.getParentOtype(), orgDO.getOid(), orgDO.getOtype(), CommonUtil.getUser().getOid());
            }
        }
    }

    public boolean checkExistName(OrgExtParamDTO orgExtParamDTO) {
        if (StringUtils.isEmpty(orgExtParamDTO.getName())) {
            return false;
        } else {
            TyplmEntityBaseUtil.checkParamNotNull(orgExtParamDTO.getParentOid(), "parentOid");
            return this.tyOrgMapper.checkExistName(orgExtParamDTO);
        }
    }

    private OrgDO bulidNewOrgDO(String name, BigInteger oid, String description, CTyEntityBaseDO container, IdentifierEntity domain) {
        OrgDO orgDO = new OrgDO();
        orgDO.setOid(oid);
        orgDO.setOtype("ty.inteplm.org.CTyOrg");
        orgDO.setName(name);
        orgDO.setDescription(description);
        if (Objects.nonNull(container)) {
            orgDO.setContaineroid(container.getOid());
            orgDO.setContainerotype(container.getOtype());
        }

        if (Objects.nonNull(domain)) {
            orgDO.setDomainoid(domain.getOid());
            orgDO.setDomainotype(domain.getOtype());
        }

        orgDO.setDisabled(0L);
        orgDO.setInternal(0L);
        orgDO.setInheriteddomain(0L);
        orgDO.setRepairneeded(0L);
        orgDO.setReplicate(0L);
        EntityBaseUtil.fillCommonFieldForCreate(orgDO);
        TyplmLoggerUtil.debug(log, () -> {
            return "newOrgDO的出参orgDO为<==【{}】";
        }, () -> {
            return new Object[]{JSON.toJSONString(orgDO)};
        });
        return orgDO;
    }

    @Override
    public boolean checkUser(UserDO user , String groupName) {
        //获取用户组织容器
        BigInteger containerOid = user.getContaineroid();
        String containerType = user.getContainerotype();
        PrincipalParamDTO principalParamDTO = new PrincipalParamDTO();
        principalParamDTO.setContaineroid(containerOid);
        principalParamDTO.setContainerotype(containerType);
        principalParamDTO.setCurPage(1);
        principalParamDTO.setPageSize(999);
        principalParamDTO.setNeedTotal(Boolean.TRUE);
        PageInfo<GroupDO> groupDOPageInfo = typlmGroupService.queryGroupByContainer(principalParamDTO);
        GroupDO groupDO = groupDOPageInfo.getList().stream().filter(k -> groupName.equals(k.getDisplayFullName())).findFirst().orElse(null);
        //群组不存在的情况下
        if (groupDO == null) {
            throw RTErrorCodeEnum.USER_NOT_FOUND.getException("用户所在组织不包含:【"+groupName+"】;群组");
        }
        PrincipalEntity principalEntity = new PrincipalEntity();
        principalEntity.setOid(groupDO.getOid());
        principalEntity.setOtype(groupDO.getOtype());
        principalEntity.setDisabled(0L);
        List<PrincipalEntity> principalOutChildren = typlmPrincipalService.getPrincipalOutChildren(principalEntity, null);
        return principalOutChildren.stream().anyMatch(k -> user.getOid().equals(k.getOid()));
    }
}
